import json
import time

from fastapi import Request, APIRouter, HTTPException, Depends
from fastapi.security import HTTPAuthorizationCredentials
from flask import Response
from starlette import status
from pydantic import BaseModel
from fastapi.responses import JSONResponse
import typing
from fastapi import FastAPI, APIRouter
from fastapi.staticfiles import StaticFiles
from amis import Page, App, Service
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import HTMLResponse

from starlette.background import BackgroundTask


class AmisJSONResponse(JSONResponse):
    def __init__(
            self,
            content: typing.Any,
            status_code: int = 200,
            headers: typing.Optional[typing.Dict[str, str]] = None,
            media_type: typing.Optional[str] = None,
            background: typing.Optional[BackgroundTask] = None,
            msg: str = "成功"
    ) -> None:
        content = {
            "status": 0,
            "msg": msg,
            "data": content
        }
        if status_code >= 400:
            content["status"] = status_code

        status_code = 200

        super().__init__(content, status_code, headers, media_type, background)


class PageApp(FastAPI):
    def register_js(self, js_root_path, directory):
        self.mount(js_root_path, StaticFiles(directory=directory), name="amis-js")

    def register_public(self, static_path="/public"):
        self.mount(static_path, StaticFiles(directory="public"), name="public")

    def register_admin_app(self, web_url, js_admin_router_url, brandName="测试Demo", logo: str = None):
        @self.get(web_url)
        def func():
            app_ = App()
            app_.brandName = brandName
            app_.api = {
                "url": "${serverUrl}" + js_admin_router_url,
                "method": "get",
                "dataType": "application/json"
            }
            app_.logo = logo
            return HTMLResponse(app_.render())

    def register_page(self, web_url, js_url):
        @self.get(web_url)
        def func():
            return HTMLResponse(Page(body=Service(schemaApi=f"js:{js_url}")).render())

    def register_middleware(self):
        @self.middleware("http")
        async def add_process_time_header(request: Request, call_next):
            start_time = time.time()
            response: Response = await call_next(request)
            if response.status_code == 401:
                return AmisJSONResponse(content={}, msg="未登录，请登录", status_code=401)
            elif response.status_code == 404:
                return AmisJSONResponse(content={}, msg="未找到该接口", status_code=404)
            elif response.status_code >= 400:
                return AmisJSONResponse(content={}, msg="系统内部未知异常,请根据状态判断", status_code=response.status_code)
            process_time = time.time() - start_time
            response.headers["X-Process-Time"] = str(process_time)
            return response

    def register_amis_static_forward(self):
        @self.get("/forward/{local_path}")
        def func(local_path: str):
            with open(local_path, "r", encoding="utf8") as f:
                return AmisJSONResponse(content=f.read(), msg="成功")


class APIRegister:
    auth_type = "sk"  # Bearer
    auth = False

    def check_auth(self, request: Request):
        if self.auth and self.auth_type not in request.headers.get("token", ""):
            raise HTTPException(status_code=401, detail="Unauthorized")


class ModelRegister(APIRegister):
    base_url = "/crud/"
    primary_key = "id"

    primary_key_url = ""

    def __init__(self, **kwargs):
        super(ModelRegister, self).__init__(**kwargs)

    def register(self, router: APIRouter):
        self.primary_key_url = self.base_url + "{" + self.primary_key + "}"
        router.add_api_route(self.primary_key_url, endpoint=self.get_item, methods=["GET"], )
        router.add_api_route(self.primary_key_url, endpoint=self.delete_item, methods=["DELETE"], )
        router.add_api_route(self.primary_key_url, endpoint=self.put_item, methods=["PUT"], )
        router.add_api_route(self.primary_key_url, endpoint=self.options_item, methods=["OPTIONS"], )
        router.add_api_route(self.base_url, endpoint=self.get_items, methods=["GET"], )
        router.add_api_route(self.base_url, endpoint=self.post_item, methods=["POST"], )

    def get_item(self, request: Request):
        return {}

    def delete_item(self, request: Request):
        return {}

    def put_item(self, request: Request):
        return {}

    def options_item(self, request: Request):
        return {}

    def get_items(self, request: Request):
        return []

    def post_item(self, request: Request):
        return {}
